use axum_app_common::{model::SessionContext, validator::RequestValidatorField};
use axum_app_dao::{
    entity::{
        self, RbacUserRoleRelActiveModel, RbacUserRoleRelColumn, RbacUserRoleRelEntity,
        SysRoleColumn, SysRoleEntity,
    },
    role_dal,
};
use sea_orm::{ActiveModelTrait, ColumnTrait};
use sea_orm::{DatabaseConnection, EntityTrait, QueryFilter, Set};

use crate::handler::user;

pub struct RoleSvc<'a> {
    db_conn: &'a DatabaseConnection,
    ctx: Option<&'a SessionContext>,
}

impl<'a> RoleSvc<'a> {
    pub fn new(db_conn: &'a DatabaseConnection, ctx: Option<&'a SessionContext>) -> Self {
        Self { db_conn, ctx }
    }
}

impl<'a> RoleSvc<'a> {
    pub async fn create(&self, code: &str, name: &str, description: &str) -> anyhow::Result<u64> {
        role_dal::insert(self.db_conn, code, name, description).await
    }

    pub async fn bind_role(&self, userid: &str, role_codes: Vec<&str>) -> anyhow::Result<()> {
        let db = self.db_conn;

        if role_codes.is_empty() {
            return Ok(());
        }

        let res_list = SysRoleEntity::find()
            .filter(SysRoleColumn::RoleCode.is_in(role_codes))
            .all(db)
            .await?;
        if res_list.is_empty() {
            return Ok(());
        }

        for role in res_list {
            let model = RbacUserRoleRelActiveModel {
                user_id: Set(userid.to_string()),
                role_code: Set(role.role_code),
                ..<RbacUserRoleRelActiveModel as ActiveModelTrait>::default()
            };
            let _ = RbacUserRoleRelEntity::insert(model).exec(db).await;
        }
        Ok(())
    }

    /**
     * 关系解除
     */
    pub async fn unbind_role(&self, userid: &str, role_codes: Vec<&str>) -> anyhow::Result<u64> {
        let db = self.db_conn;

        if userid.is_blank() {
            return Ok(0);
        }

        if role_codes.is_empty() {
            return Ok(0);
        }

        let res = RbacUserRoleRelEntity::delete_many()
            .filter(RbacUserRoleRelColumn::UserId.eq(userid))
            .filter(RbacUserRoleRelColumn::RoleCode.is_in(role_codes))
            .exec(db)
            .await?;

        Ok(res.rows_affected)
    }
}
